<template>
  <BasicModal
    width="60%"
    v-bind="$attrs"
    @register="registerModal"
    okText="确定"
    cancelText="取消"
    :title="getTitle"
    :canFullscreen="false"
    :defaultFullscreen="true"
    @cancel="handleCancel"
    :footer="null"
    :showOkBtn="false"
  >
    <a-layout class="spider-detail-container">
      <a-layout-header>
        <template :key="'header-icon-' + index" v-for="(item, index) in headerBtns">
          <a-tooltip :title="item.title" placement="bottom" v-if="item.type === 'icon'">
            <Icon
              :icon="item.icon"
              :size="20"
              @click="headerBtnItemHandle(item.click)"
              :style="{ color: item.click.disable == true ? '#ccc' : '#1890ff' }"
            />
          </a-tooltip>
          <a-divider :key="'header-icon-' + index" type="vertical" v-if="item.type === 'divider'" />
        </template>
        <TestModal
          :editor="rpaEditor"
          :cell="selectCell"
          ref="testModalRef"
          @handleShowBtn="handleShowBtn"
          @debugMessage="handleDebugMessage"
          style="pointer: events"
        />
        <HistoryVersionModal :id="flowId" :editor="rpaEditor" ref="historyversionmodal" />
      </a-layout-header>
      <a-layout class="box">
        <a-layout-sider :width="getSliderWidth">
          <div class="spider-toolbar-container" ref="toolbarRef"></div>
        </a-layout-sider>
        <a-layout-content class="spider-content">
          <div v-show="codeEditorShow !== true" class="spider-editor-container" ref="flowEditorRef"></div>
          <CodeEditor v-show="codeEditorShow === true" v-model:value="codeEditorValue" :mode="coneEditorMode" @change="handleCodeEditorChange" />
        </a-layout-content>
        <template v-if="isShowRight">
          <Resizer position="left" @move="onFootMove" />
        </template>
        <a-layout-footer class="spider-properties-container right" v-if="isShowRight" :style="{ width: getFooterWidth }">
          <PropertySetting :graphCell="selectCell" :message="message" :showTips="showTips" :direction="direction" />
        </a-layout-footer>
      </a-layout>
      <template v-if="isShowBottom">
        <Resizer position="top" @move="onFootMove" />
      </template>
      <a-layout-footer class="spider-properties-container bottom" v-if="isShowBottom" :style="{ height: getFooterHeight }">
        <PropertySetting :graphCell="selectCell" :message="message" :showTips="showTips" :direction="direction" />
      </a-layout-footer>
    </a-layout>
  </BasicModal>
</template>

<script lang="ts" setup>
  import { onMounted, onUnmounted, nextTick, ref, Ref, unref, reactive, computed, watch, getCurrentInstance, toRaw, markRaw } from 'vue';
  import { BasicModal, useModalInner } from '/@/components/Modal';
  import { useRouter } from 'vue-router';
  import HeaderBtnsJson from './json/header-btns.json';
  import Icon from '/@/components/Icon';
  import { getXml, saveFlow } from './design.api';
  import { Modal } from 'ant-design-vue';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { CodeEditor } from '/@/components/CodeEditor';
  import PropertySetting from './propertysetting';
  import TestModal from './components/testModal.vue';
  import HistoryVersionModal from './components/historyVersionModal.vue';
  import Resizer from './components/Resizer.vue';
  import { JsonProperty } from '/@/utils/graph/Graph';
  import { RpaEditor } from './utils/render/index';
  import printJS from 'print-js';

  const { currentRoute } = useRouter();
  const { createMessage: $message } = useMessage();

  const route = unref(currentRoute);
  
  // 当前选中的图形节点
  const selectCell: any = ref({
    id: '',
    data: new JsonProperty({}),
  });
  const message = ref();
  // DEBUG时显示数据提示
  const showTips = ref(false);
  // 是否显示流程编辑器
  const show = ref(false);
  // 流程数据更新或新建
  const isUpdate = ref(true);
  // 流程数据ID
  const flowId = ref('');
  // 流程数据NAME
  const flowName = ref('');
  // 图形编辑器
  const rpaEditor = ref<RpaEditor>();
  // 流程编辑器
  const flowEditorRef = ref<HTMLElement | null>(null);
  // 侧边工具栏
  const toolbarRef = ref<HTMLElement | null>(null);
  // 属性面板DOCK
  const direction = ref('bottom');
  // XML编辑器
  const codeEditorValue = ref();
  const coneEditorMode = ref('xml');
  const codeEditorShow = ref(false);
  // 测试模块
  const testModalRef = ref();
  const getSliderWidth = ref(50);
  const offsetXmoved = ref(0);
  const offsetYmoved = ref(0);
  const footerWidth = ref(480);
  const footerHeight = ref(200);
  // 历史版本
  const historyversionmodal = ref();
  // 所有头部按钮数据
  const headerBtns = reactive(HeaderBtnsJson);
  // 属性底部展示
  const isShowBottom = ref(true);
  // 属性右侧展示
  const isShowRight = ref(false);

  // 注册模态框
  const [registerModal, {}] = useModalInner(async (data) => {
    if (flowEditorRef.value) {
      flowEditorRef.value.innerHTML = '';
    }
    if (toolbarRef.value) {
      toolbarRef.value.innerHTML = '';
    }
    rpaEditor.value = new RpaEditor({
      graphContainer: flowEditorRef.value,
      handleCellChangedListener: handleCellChangedListener,
      toolbarContainer: toolbarRef.value,
      allowZoom: false,
    });
    handleDockToBottom();
    addKeyDownEventListener();
    show.value = true;
    codeEditorShow.value = false;
    isUpdate.value = !!data?.isUpdate;
    if (unref(isUpdate)) {
      flowId.value = data.record.id;
      flowName.value = data.record.name;
      const res = await getXml({ id: flowId.value });
      rpaEditor.value?.getGraph().inputXml(res);
    }
    rpaEditor.value?.getGraph().fireCellSelectedEvent();
    getSliderWidth.value = rpaEditor.value?.getSlideBarSize();
  });

  // 标题
  const getTitle = computed(() => (!unref(isUpdate) ? '新增流程设计' : '编辑流程设计【' + flowName.value + '】'));

  watch(
    () => message.value,
    (val) => {
      if (!val) {
        headerBtns.forEach((item) => {
          if (item.title === '下一步') {
            item.click.disable = true;
          }
        });
      }
    },
    { immediate: true, deep: true }
  );

  watch(
    () => selectCell.value.value,
    (val) => {
      //console.log('wang-watch-value', rpaEditor.value, selectCell.value, val);
      if(selectCell.value && val){
        rpaEditor.value?.getGraph().setCellValue(selectCell.value, val);
      }
    },
    { immediate: true, deep: true }
  );

  const getFooterWidth = computed(() => {
    let footerMinWidth = 400;
    let footerMaxWidth = 750;
    let width = footerWidth.value + offsetXmoved.value;
    if (width < footerMinWidth) {
      width = footerMinWidth;
    } else if (width > footerMaxWidth) {
      width = footerMaxWidth;
    }
    return width + 'px';
  });

  const getFooterHeight = computed(() => {
    let footerMinHeight = 200;
    let footerMaxHeight = 650;
    let height = footerHeight.value + offsetYmoved.value;
    if (height < footerMinHeight) {
      height = footerMinHeight;
    } else if (height > footerMaxHeight) {
      height = footerMaxHeight;
    }
    return height + 'px';
  });

  function onFootMove(_event, offsetX: number, offsetY: number) {
    offsetXmoved.value = offsetXmoved.value - offsetX;
    offsetYmoved.value = offsetYmoved.value - offsetY;
    getSliderWidth.value = rpaEditor.value?.getSlideBarSize()!;
  }

  function addKeyDownEventListener() {
    document.addEventListener('keydown', keyboardDown, true);
  }

  function removeKeyDownEventListener() {
    document.removeEventListener('keydown', keyboardDown, true);
  }

  function keyboardDown(evt: KeyboardEvent) {
    if (codeEditorShow.value) {
      return;
    }
    if (evt.target?.localName == 'input') {
      return;
    }
    headerBtns.forEach((element) => {
      if (element.exeFunKey && element.exeFunKey.length > 0) {
        if (
          (evt.ctrlKey && element.exeFunKey.indexOf(evt.key.toLowerCase()) !== -1) ||
          (evt.altKey && element.exeFunKey.indexOf(evt.key.toLowerCase()) !== -1) ||
          (element.exeFunKey.length === 1 && element.exeFunKey.indexOf(evt.key.toLowerCase()) !== -1)
        ) {
          headerBtnItemHandle(element.click);
          evt.preventDefault(); //阻止浏览器默认行为
        }
      }
    });
  }

  /**
   * 节点变更事件
   */
  function handleCellChangedListener(cell) {
    selectCell.value = cell;
  }

  /**
   * 验证流程内容
   */
  function validXML(callback) {
    var cell = rpaEditor.value?.getGraph().valid();
    if (cell) {
      Modal.confirm({
        title: '异常处理',
        content: `<div style="color:red;">检测到有箭头未连接到节点上，是否处理？</div>`,
        okText: '处理',
        cancelText: '忽略',
        onOk: () => {
          rpaEditor.value?.getGraph().setCellSelected(cell);
        },
        onCancel: () => {
          callback && callback();
        },
      });
    } else {
      callback && callback();
    }
  }

  /**
   * XML编辑器内容变更事件
   */
  function handleCodeEditorChange(content) {
    rpaEditor.value?.getGraph().inputXml(content);
  }

  /**
   * 保存流程内容
   */
  function handleSave() {
    validXML(async () => {
      let params: any = {};
      params.id = flowId.value;
      params.xml = rpaEditor.value?.getGraph().outPutXml();
      params.name = rpaEditor.value?.getGraph().getRoot().data.get('spiderName') || '未定义名称';
      const { success, data, msg } = await saveFlow(params);
      if (success) {
        flowId.value = data;
        $message.success('保存成功');
      } else {
        $message.error(msg);
      }
    });
  }

  /**
   * 流程图执行事件
   */
  function handleFlowExecute(exe) {
    rpaEditor.value?.getGraph().execute(exe);
  }

  /**
   * 删除选中节点事件
   */
  function handleDeleteSelectCells() {
    rpaEditor.value?.getGraph().deleteSelectedCells();
  }

  /**
   * 打印当前xml到console事件
   */
  function handlePrintXmlToConsole() {
    //console.log(rpaEditor.value?.getGraph().outPutXml());
    // printJS({
    //       printable: ['https://anncwb.github.io/anncwb/images/preview1.png', 'https://anncwb.github.io/anncwb/images/preview2.png'],
    //       type: 'image',
    //       header: 'Multiple Images',
    //       imageStyle: 'width:100%;',
    //     });
    rpaEditor.value?.getGraph().outPutImage();
  }

  /**
   * 获取版本历史记录事件
   */
  function handleHistoryVersion() {
    historyversionmodal.value.historyAction();
  }

  /**
   * 切换XML页面事件
   */
  async function handleChangeXmlPage() {
    codeEditorValue.value = rpaEditor.value?.getGraph().outPutXml();
    codeEditorShow.value = !codeEditorShow.value;
    flowEditorRef.value?.focus();
  }

  /**
   * 调试/测试事件
   */
  function handleTest(debug) {
    headerBtns.forEach((item) => {
      if (debug === 'false') {
        // 测试模式
        if (item.title === '测试（Ctrl+Q）' || item.title === '调试' || item.title === '下一步') {
          item.click.disable = true;
        }
        if (item.title === '停止') {
          item.click.disable = false;
        }
      } else {
        // 调试模式
        if (item.title === '测试（Ctrl+Q）' || item.title === '调试') {
          item.click.disable = true;
        }
        if (item.title === '下一步' || item.title === '停止') {
          item.click.disable = false;
        }
        // 打开提示
        showTips.value = true;
      }
    });
    testModalRef.value.testAction(debug);
  }

  /**
   *
   */
  function handleDebugMessage(msg) {
    message.value = msg;
  }

  /**
   * 下一步事件
   */
  function handleNext() {
    testModalRef.value.handleNext();
  }

  /**
   * 停止事件
   */
  function handleStop() {
    testModalRef.value.handleStop();
  }

  /**
   * 测试模式下按钮控制
   */
  function handleShowBtn(close) {
    if (close) {
      // 关闭提示
      showTips.value = false;
    }
    headerBtns.forEach((item) => {
      if (item.title === '下一步' || item.title === '停止') {
        if (close) {
          item.click.disable = false;
        } else {
          item.click.disable = true;
        }
      }
      if (item.title == '测试（Ctrl+Q）' || item.title === '调试') {
        if (close) {
          item.click.disable = true;
        } else {
          item.click.disable = false;
        }
      }
    });
  }

  /**
   * Dock to right
   */
  function handleDockToRight() {
    direction.value = 'right';
    isShowBottom.value = false;
    isShowRight.value = true;
    resetDistance();
  }

  /**
   * Dock to bottom
   */
  function handleDockToBottom() {
    direction.value = 'bottom';
    isShowBottom.value = true;
    isShowRight.value = false;
    resetDistance();
  }

  function resetDistance() {
    footerWidth.value = 480;
    footerHeight.value = 200;
    offsetXmoved.value = 0;
    offsetYmoved.value = 0;
  }

  /**
   * 头部按钮事件处理
   */
  function headerBtnItemHandle(item) {
    headerBtnHandle(item.name, item.params, item.disable);
  }


  /**
   *  头部按钮事件处理
   */
  function headerBtnHandle(methodName, params, disable) {
    // 收集所有方法
    const actions = {
      handleSave, 
      handleTest, 
      handleFlowExecute, 
      handleHistoryVersion, 
      handleDeleteSelectCells, 
      handleChangeXmlPage, 
      handlePrintXmlToConsole, 
      handleNext, 
      handleStop, 
      handleDockToRight, 
      handleDockToBottom};
    if (disable === false) {
      const action = actions[methodName as keyof typeof actions];
      console.log(methodName, action);
      action && action(params);
    }
  }

  /**
   * 关闭模态框事件
   */
  function handleCancel() {
    // 重置表单
    show.value = false;
    flowId.value = '';
    flowName.value = '';
    selectCell.value = {
      id: '',
      data: new JsonProperty({}),
    };
    rpaEditor.value?.destroy();
    removeKeyDownEventListener();
    testModalRef.value?.handleClose();
  }
</script>

<style lang="less">
  @import './less/design.less';
  .jv-node .jv-node {
    width: 500px;
  }
  .right {
    display: flex;
    height: 100% !important;
    padding: 0 10px !important;
    user-select: none !important;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
  }
  .bottom {
    padding: 0 10px !important;
    user-select: none !important;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
  }
  .spider-detail-container .ant-layout-footer {
    z-index: 1005;
  }
</style>
